#ifndef MAPPING_HPP
#define MAPPING_HPP

#include "Basic/Array.hpp"

namespace GxLibBasic
{
	template <typename T1, typename T2, typename _Comp>
	class gxMappingItem
	{
	private:
		_Comp Comparator;
	public:
		T1 Key;
		T2 Value;

		gxMappingItem(T1 k, T2 val)
			:Key(k), Value(val)
		{
		}

		gxMappingItem()
		{}

		gxMappingItem(const gxMappingItem &a)
		{
			Key = a.Key;
			Value = a.Value;
		}

		bool operator > (const T1 &k)
		{
			return Comparator.Compare(Key, k) == gxcrGreater;
		}

		bool operator < (const T1 &k)
		{
			return Comparator.Compare(Key, k) == gxcrLess;
		}

		bool operator == (const T1 &k)
		{
			return Comparator.Compare(Key, k) == gxcrEqual;
		}
	};

	template <typename T1, typename T2, typename _Comp = gxStandardComparator, typename _GrowStrategy = gxStandardGrowStrategy>
	class Mapping
	{
	protected:
		OrderedArray<gxMappingItem<T1,T2,_Comp>,false,gxStandardComparator,_GrowStrategy> FDict;
	public:
		Int Count()
		{
			return FDict.Count();
		}
		gxMappingItem<T1,T2,_Comp> & operator [](Int x)
		{
			return FDict[x];
		}
		bool Add(T1 Key, T2 Value)
		{
			if (!FDict.Exists(Key))
			{
				FDict.Add(gxMappingItem<T1,T2,_Comp>(Key,Value), Key);
				return true;
			}
			else
				return false;
		};
		void SetMapping(T1 Key, T2 v)
		{
			if (!Add(Key,v))
			{
				Int id = FDict.Find(Key);
				FDict[id].Value = v;
			}
		};
		void Remove(T1 Key)
		{
			Int id = FDict.Find(Key);
			if (id != -1)
				FDict.Delete(id);
		}
		bool Lookup(T1 Key, T2 &rs) const
		{
			Int id = FDict.Find(Key);
			if (id != -1)
			{
				rs = FDict[id].Value;
				return true;
			}
			else
				return false;
		}
		T2 * GetValuePointer(T1 Key)
		{
			Int id = FDict.Find(Key);
			if (id != -1)
				return &FDict[id].Value;
			else
				return 0;
		}
		bool BackwardLookup(T2 val, T1 &key) const
		{
			for (int i=0; i<FDict.Count(); i++)
				if (FDict[i].Value == val)
				{
					key = FDict[i].Key;
					return true;
				}
			return false;
		}
		void Clear()
		{
			FDict.Clear();
		}
	};
}
#endif